package com.example.springboot_jap_model.aspect;

import com.example.springboot_jap_model.constant.Constant;
import com.example.springboot_jap_model.domain.Authority;
import com.example.springboot_jap_model.domain.User;
import com.example.springboot_jap_model.domain.UserAndRole;
import com.example.springboot_jap_model.enums.RespEntityEnum;
import com.example.springboot_jap_model.exception.AutoException;
import com.example.springboot_jap_model.service.UserService;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Lookup;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.thymeleaf.util.ListUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.List;


/**
 * 注解 说明
 * 1.aop注解
 * 2.引入容器
 */
@Aspect
@Component
public class HttpAspect {


    @Autowired
    private UserService userService;

    private final static Logger logger = LoggerFactory.getLogger(HttpAspect.class);

    @Pointcut("execution(public * com.example.springboot_jap_model.controller.*.*(..))")
    public void model() {

    }


    /**
     * 包含参数打印和权限的拦截功能
     *
     * @param joinPoint
     */
    @Before("model()")
    public void before(JoinPoint joinPoint) {
        logger.info("---------------------开始进入Before 参数打印----------------------------");
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        //url
        logger.info("url={}", request.getRequestURI());
        //请求类型
        logger.info("method={}", request.getMethod());
        //ip 地址
        logger.info("ip={}", request.getRemoteAddr());
        //类名 和 方法名
        logger.info("class_method={}", joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
        //参数 （但仅显示了第一个参数 思考）
        logger.info("args={}", joinPoint.getArgs());
        //参数个数
        logger.info("args_length={}", joinPoint.getArgs().length);
        //权限 校验
        HttpSession session = request.getSession();
        User user = (User) session.getAttribute(Constant.SESSION_LOGIN);
        if (user != null) {
            logger.info("---------------------权限拦截 开始----------------------------");
            List<Authority> authorityList = userService.findAllAuthByUrl(request.getRequestURI());
            //判断 权限是否存在 的原因是 区分 是否是权限需要控制的
            if (!ListUtils.isEmpty(authorityList)) {
                logger.info("请求路径权限:{},{}", request.getRequestURI(), "存在");
                List<UserAndRole> authenticatorList = userService.findAutoByUserIdAndUrl(user.getId(), request.getRequestURI());
                // 请求是 关于权限的 但是 这个用户无权限 抛出异常
                if (ListUtils.isEmpty(authenticatorList)) {
                    if (user.getType() == Constant.GL_USER_TYPE) {
                        //管理员 生成权限
                        userService.distributionAuth();
                    } else {
                        throw new AutoException(RespEntityEnum.AUTO_FILTER);
                    }
                }
            }
        }
        //异常测试
        //throw new AutoException(RespEntityEnum.AUTO_FILTER);
    }

    /**
     * 打印 返回值 在日志
     *
     * @param object
     */
    @AfterReturning(returning = "object", pointcut = "model()")
    public void doAfterReturning(Object object) {
        logger.info("返回参数打印:Response={}", object.toString());
    }


}
